package tienich360.com.lib;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONObject;

public class JsonConvert {

	public static <T> T DeserializeObject(Class<T> cls, JSONObject json)
			throws Exception {
		T obj = null;
		obj = (T) (cls.newInstance());
		// JSONObject json = new JSONObject(value);
		Field[] fields = obj.getClass().getDeclaredFields();
		for (Field field : fields) {
			if (json.has(field.getName())) {
				String jsonName = field.getName();
				field.setAccessible(true);
				if (field.getType() == int.class) {
					setValue(field, obj, json.getInt(jsonName));
					// field.set(obj, json.getInt(field.getName()));
				} else if (field.getType() == String.class) {
					String valueData = json.getString(field.getName());
					// field.set(obj, valueData);
					setValue(field, obj, valueData);
				} else if (field.getType() == Double.class) {
					// field.set(obj, json.getDouble(field.getName()));
					setValue(field, obj, json.getDouble(field.getName()));
				} else if (field.getType() == Integer.class) {
					setValue(field, obj, json.getInt(field.getName()));
					// field.set(obj, json.getInt(field.getName()));
				} else if (field.getType() == Boolean.class) {
					setValue(field, obj, json.getBoolean(field.getName()));
					// field.set(obj, json.getBoolean(field.getName()));
				} else if (field.getType() == Long.class) {
					// field.set(obj, json.getLong(jsonName));
					setValue(field, obj, json.getLong(jsonName));
				} else if (field.getType() == ArrayList.class) {
					ParameterizedType fieldListType = (ParameterizedType) field
							.getGenericType();
					Class<?> fieldListClass = (Class<?>) fieldListType
							.getActualTypeArguments()[0];
					JSONArray jarray = json.getJSONArray(field.getName());
					Object o = DeserializeArray(fieldListClass, jarray);
					// field.set(obj, o);
					setValue(field, obj, o);
				} else {
					Object o = DeserializeObject(field.getType(),
							json.getJSONObject(field.getName()));
					// field.set(obj, o);
					setValue(field, obj, o);
				}
			}
		}
		return obj;

	}

	private static void setValue(Field field, Object obj, Object value)
			throws Exception {
		if (field.isAccessible()) {
			field.set(obj, value);
		} else {
			String methodSet = (field.getName().charAt(0) + "").toUpperCase()
					+ field.getName().substring(1) + "";
			methodSet = "set" + methodSet;
			Method method = obj.getClass()
					.getMethod(methodSet, field.getType());
			method.invoke(obj, value);
		}
	}

	public static <T> ArrayList<T> DeserializeArray(Class<T> cls,
			JSONArray jarray) throws Exception {
		ArrayList<T> list = new ArrayList<T>();
		for (int i = 0; i < jarray.length(); i++) {
			T obj = DeserializeObject(cls, jarray.getJSONObject(i));
			list.add(obj);
		}
		return list;
	}

	public static <T> ArrayList<T> DeserializeArray(Class<T> cls,
			JSONArray jarray, ArrayList<T> list) throws Exception {
		if (list == null)
			list = new ArrayList<T>();
		for (int i = 0; i < jarray.length(); i++) {
			T obj = DeserializeObject(cls, jarray.getJSONObject(i));
			list.add(obj);
		}
		return list;
	}
}
